package com.xpand.guava;

import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Ordering;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @Author: wei.wang
 * @Description: Ordering 学习
 * @Date 2017/12/27 9:59
 * @Modified
 */
public class OrderingTest {

    public static void main(String[] args) {
        // 按level排序 ordering
        Ordering<Person> levelOrdering = Ordering.natural().nullsFirst().onResultOf(FuncationInfo.LEVEL);
        Ordering<Person> thenEgaOrdering = Ordering.natural().nullsFirst().onResultOf(FuncationInfo.AGE);
        Ordering<Person> thenFirstNameOrdering = Ordering.natural().nullsFirst().onResultOf(FuncationInfo.FIRSTNAME);
        Ordering<Person> thenLastNameOrdering = Ordering.natural().nullsFirst().onResultOf(FuncationInfo.LASTNAME);


        List<Person> personList = new ArrayList<Person>();
        personList.add(new Person("a", "a", 18, 'D'));
        personList.add(new Person("a", "b", 18, 'D'));
        personList.add(new Person("a", "c", 18, 'D'));
        personList.add(new Person("a", "a", 17, 'D'));
        personList.add(new Person("a", "a", 19, 'D'));
        personList.add(new Person("a", "a", 18, 'A'));
        personList.add(new Person("a", "a", 18, 'B'));
        personList.add(new Person("a", "a", 18, 'E'));
        personList.add(new Person("b", "a", 18, 'D'));
        personList.add(new Person("c", "a", 18, 'D'));
        personList.add(new Person("d", "a", 18, 'D'));

        System.out.println("order by level");
        Collections.sort(personList, levelOrdering);
        System.out.println(personList);

        Collections.shuffle(personList);

        System.out.println("order by level and age");
        Collections.sort(personList, levelOrdering.compound(thenEgaOrdering));
        System.out.println(personList);

        System.out.println("order by level and age and firstName");
        Collections.sort(personList, levelOrdering.compound(thenEgaOrdering).compound(thenFirstNameOrdering));
        System.out.println(personList);

        System.out.println("order by level and age and firstName");
        Collections.sort(personList, levelOrdering.compound(thenEgaOrdering).compound(thenFirstNameOrdering).compound(thenLastNameOrdering));
        System.out.println(personList);
    }
}

enum FuncationInfo implements Function<Person, Comparable>{
    AGE{
        @Override
        public Comparable apply(Person person) {
            return person.getAge();
        }
    },
    LEVEL{
        @Override
        public Comparable apply(Person person) {
            return person.getLevel();
        }
    },
    FIRSTNAME{
        @Override
        public Comparable apply(Person person) {
            return person.getFirstName();
        }
    },
    LASTNAME{
        @Override
        public Comparable apply(Person person) {
            return person.getLastName();
        }
    };
}

// 复杂排序对象
class Person{
    private String firstName;
    private String lastName;
    private int age;
    // 身份级别
    private char level;

    public Person(String firstName, String lastName, int age, char level) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.level = level;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("firstName", firstName)
                .add("lastName", lastName)
                .add("age", age)
                .add("level", level)
                .toString();
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getLevel() {
        return level;
    }

    public void setLevel(char level) {
        this.level = level;
    }
}
